package com.ease.component.controls {
   import com.ease.component.controls.datagridclass.ISelectable;

   import flash.events.MouseEvent;
   import flash.ui.Keyboard;

   import mx.controls.AdvancedDataGrid;
   import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
   import mx.controls.listClasses.IListItemRenderer;
   import mx.core.ClassFactory;
   import mx.core.ISelectableList;

   public class AdvancedDataGridEx extends AdvancedDataGrid {
      public function AdvancedDataGridEx() {
         super();
         this.sortExpertMode = true;
         this.headerRenderer = new ClassFactory(LabelHeaderRenderer);
      }

      /**
       * A function that will filter a item renderer as selection disabled in the datagrid.
       * That means that you can perform an operation (click a button, a checkbox or a radio button
       * on this item renderer or just simply click on this item renderer itself) but it won't
       * trigger the event to make the row of this item renderer selected.
       * The function will be set in following form:
       * function(item:IListItemRenderer):Boolean;
       * If the function return true, that means the item renderer will be filtered as disabled.
       */
      public var itemRendererSelectionDisabledFunction:Function;

      /**
       * A function that will filter a row as selection disabled in the datagrid.
       * The function will be set in following form:
       * function(data:Object):Boolean;
       * If the function return true, that means the row containing the data will be filtered as disabled.
       */
      public var rowDataSelectionDisabledFunction:Function;

      public var showItemHighlight:Boolean = true;

      public var showItemSelection:Boolean = true;

      public var showItemCaret:Boolean = true;

      public var loadingState:String = "loaded";

      override protected function updateDisplayOfItemRenderer(r:IListItemRenderer):void {
         if(r && r.data) {
            var itemSelectable:Boolean = !disableRowData(r.data);
            if(r is ISelectable) {
               ISelectable(r).selectable = itemSelectable;
            }
            else {
               r.enabled = itemSelectable;
            }
         }
         super.updateDisplayOfItemRenderer(r);
      }

      protected function disableRowData(data:Object):Boolean {
         if(rowDataSelectionDisabledFunction != null) {
            return rowDataSelectionDisabledFunction(data);
         }
         return false;
      }

      protected function disableItemRenderer(item:IListItemRenderer):Boolean {
         if(itemRendererSelectionDisabledFunction != null) {
            return itemRendererSelectionDisabledFunction(item);
         }
         return false;
      }

      override protected function selectItem(item:IListItemRenderer,
                                             shiftKey:Boolean,
                                             ctrlKey:Boolean,
                                             transition:Boolean=true):Boolean {
         if(item && disableRowData(item.data)) {
            return false;
         }
         return super.selectItem(item, shiftKey, ctrlKey, transition);
      }

      override protected function drawItem(item:IListItemRenderer,
                                           selected:Boolean=false,
                                           highlighted:Boolean=false,
                                           caret:Boolean=false,
                                           transition:Boolean=false):void {
         super.drawItem(item,
            selected && showItemSelection,
            highlighted && showItemHighlight,
            caret && showItemCaret,
            transition);

      }

      override protected function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer {
         var item:IListItemRenderer = super.mouseEventToItemRenderer(event);
         if (item && item.data && item.data is AdvancedDataGridColumn) {
            return item;
         }
         if (item && disableItemRenderer(item)) {
            return null;
         }
         if (item && item.data && disableRowData(item.data)) {
            return null;
         }
         return item;
      }

      override protected function moveSelectionVertically( code:uint, shiftKey:Boolean, ctrlKey:Boolean ):void {
         var i:int;
         var newIndex:int;

         switch( code ) {
            case Keyboard.UP:
               newIndex = getPreviousUnselectableIndex( caretIndex - 1 );
               break;

            case Keyboard.DOWN:
               newIndex = getNextUnselectableIndex( caretIndex + 1 );
               break;

            case Keyboard.HOME:
               newIndex = getFirstSelectableIndex();
               code = Keyboard.UP;
               break;

            case Keyboard.END:
               newIndex = getLastSelectableIndex();
               code = Keyboard.DOWN;
               break;

            case Keyboard.PAGE_UP:
               newIndex = Math.max( getFirstSelectableIndex(), getPreviousUnselectableIndex( caretIndex - ( rowCount - 2 ) ) );
               code = Keyboard.UP;
               break;

            case Keyboard.PAGE_DOWN:
               newIndex = Math.min( getLastSelectableIndex(), getNextUnselectableIndex( caretIndex + ( rowCount - 1 ) ) );
               code = Keyboard.DOWN;
               break;
         }

         if( newIndex > -1 && newIndex < collection.length ) {
            caretIndex = newIndex;
            super.moveSelectionVertically( code, shiftKey, ctrlKey );
         }
      }

      private function getFirstSelectableIndex():int {
         var result:int = -1;

         for( var i:int = 0; i < collection.length; i++ ) {
            if( !disableRowData( collection[i] ) ) {
               result = i + 1;
               break;
            }
         }

         return result;
      }

      private function getLastSelectableIndex():int {
         var result:int = -1;

         for( var i:int = collection.length - 1; i > -1; i-- ) {
            if( !disableRowData( collection[i] ) ) {
               result = i - 1;
               break;
            }
         }

         return result;
      }

      private function getPreviousUnselectableIndex( startIndex:int ):int {
         var result:int = -1;

         for( var i:int = startIndex; i > -1; i-- ) {
            if( !disableRowData( collection[i] ) ) {
               result = i + 1;
               break;
            }
         }

         return result;
      }

      private function getNextUnselectableIndex( startIndex:int ):int {
         var result:int = collection.length;

         for( var i:int = startIndex; i < collection.length; i++ ) {
            if( !disableRowData( collection[i] ) ) {
               result = i - 1;
               break;
            }
         }

         return result;
      }
   }
}